Popular Searches
Popular Course Categories
Popular Courses

AJAX Elements

Advanced Selenium

AJAX Elements in Selenium

AJAX (Asynchronous JavaScript and XML) is a web development technique that allows web pages to communicate with a server asynchronously and update specific parts of the page without requiring a complete page reload. Modern web applications frequently use AJAX, JavaScript, Fetch API, XMLHttpRequest, and similar technologies to load or modify content dynamically.

For Selenium automation, AJAX elements are important because an element may not immediately exist, become visible, become enabled, or contain the expected data when Selenium first tries to interact with it. Selenium's documentation notes that JavaScript-driven changes can occur after the initial page load, creating synchronization problems if the automation executes before the application reaches the required state. :contentReference[oaicite:0]{index=0}

To automate AJAX-based applications reliably, Selenium tests commonly use Explicit Waits, Expected Conditions, appropriate locators, and other synchronization techniques rather than relying on fixed delays.

Course Resource: Selenium Training | Register for Course Demo


1. What is AJAX?

AJAX stands for Asynchronous JavaScript and XML. It is a technique used by web applications to exchange data with a server asynchronously and update part of a webpage without refreshing the complete page.

Although the name contains XML, modern applications commonly exchange data using JSON, and JavaScript may use APIs such as Fetch or XMLHttpRequest.

For example, when a user types a product name into a search box, the application may send a background request to the server and display matching products without reloading the entire page.

User enters data

        |

        v

JavaScript event

        |

        v

AJAX / Fetch Request

        |

        v

Server processes request

        |

        v

Response returned

        |

        v

DOM updated dynamically

        |

        v

New/updated element available


2. Why are AJAX Elements Important in Selenium?

AJAX elements are important because Selenium automation can encounter a timing difference between the browser application and the test script.

The page's initial document may already be loaded while JavaScript is still adding elements, changing their visibility, updating text, loading data, or enabling controls.

  • Elements may appear after a delay.
  • Elements may become visible only after an AJAX response.
  • Buttons may initially be disabled and become enabled later.
  • Text may be updated dynamically.
  • Tables may receive rows asynchronously.
  • Dropdown options may be loaded dynamically.
  • Search suggestions may appear after typing.
  • Loading indicators may disappear after a server response.
  • DOM elements may be replaced during asynchronous updates.
  • Single Page Applications may continuously update the DOM.


3. AJAX Element Execution Flow

Test Starts

    |

    v

Open Web Application

    |

    v

Initial DOM Loaded

    |

    v

JavaScript Executes

    |

    v

AJAX / Fetch Request

    |

    v

Server Response

    |

    v

DOM Updated

    |

    v

Element Becomes Ready

    |

    v

Explicit Wait Condition Satisfied

    |

    v

Selenium Interacts with Element

    |

    v

Assertion


4. Static vs AJAX Elements

Static ElementAJAX/Dynamic Element
Usually available immediatelyMay appear later
Content changes less frequentlyContent can change dynamically
Simple synchronization may be enoughExplicit synchronization is often required
Usually present in initial DOMMay be added or modified after JavaScript execution
Less likely to create timing problemsMore likely to create timing problems


5. Example of an AJAX Element

Consider a search application where a user enters "Laptop". The application sends an asynchronous request and displays search suggestions.

User types: Laptop

        |

        v

AJAX request

        |

        v

Server searches products

        |

        v

Response received

        |

        v

Suggestion list updated

        |

        v

Laptop Pro

Laptop Stand

Laptop Bag

The suggestion elements may not exist at the exact moment the user finishes typing. Selenium therefore needs to synchronize with the application's state.


6. Why Thread.sleep() is Not the Best Solution

A common approach is to use Thread.sleep() after performing an AJAX action.

driver.findElement(By.id("search")).sendKeys("Laptop");

 

Thread.sleep(5000);

 

driver.findElement(By.id("result")).click();

This approach is generally inefficient because the test waits for the full duration even if the element becomes ready earlier. If the application takes longer than the hard-coded duration, the test can still fail.

Selenium recommends condition-based synchronization such as explicit waits for dynamic applications. :contentReference[oaicite:1]{index=1}


7. Explicit Wait for AJAX Elements

An Explicit Wait waits for a specific condition before continuing test execution.

WebDriverWait wait = new WebDriverWait(

    driver,

    Duration.ofSeconds(10)

);

 

WebElement element = wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.id("result")

    )

);

 

element.click();

Explicit waits are particularly useful for AJAX elements because the test can wait for the actual condition rather than an arbitrary amount of time. Selenium describes explicit waits as polling for a specific condition until it becomes true or the timeout is reached. :contentReference[oaicite:2]{index=2}


8. Expected Conditions for AJAX Elements

Selenium provides commonly used Expected Conditions for explicit waits. These include conditions for element presence, visibility, clickability, text, titles, and other states. :contentReference[oaicite:3]{index=3}

Expected ConditionPurpose
presenceOfElementLocated()Waits until the element exists in the DOM
visibilityOfElementLocated()Waits until the element is visible
elementToBeClickable()Waits until the element can be clicked
textToBePresentInElement()Waits for expected text
titleContains()Waits for a title containing specific text
stalenessOf()Waits until an old element reference is no longer attached to the DOM
invisibilityOfElementLocated()Waits until an element becomes invisible


9. presenceOfElementLocated()

This condition waits until an element is present in the DOM. Presence does not necessarily mean that the element is visible or interactable.

WebDriverWait wait = new WebDriverWait(

    driver,

    Duration.ofSeconds(10)

);

 

WebElement result = wait.until(

    ExpectedConditions.presenceOfElementLocated(

        By.id("ajaxResult")

    )

);

Use this when the main requirement is that the element exists in the DOM.


10. visibilityOfElementLocated()

This condition waits until an element is present and visible.

WebElement result = wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.id("ajaxResult")

    )

);

 

System.out.println(result.getText());

This is useful when AJAX content is inserted into the DOM but becomes visible only after a background operation completes.


11. elementToBeClickable()

Sometimes an AJAX button is present but cannot yet be interacted with. In such situations, waiting for clickability can be useful.

WebElement submitButton = wait.until(

    ExpectedConditions.elementToBeClickable(

        By.id("submit")

    )

);

 

submitButton.click();

Selenium's troubleshooting documentation specifically identifies explicit waits and clickability conditions as useful for synchronization problems. :contentReference[oaicite:4]{index=4}


12. Waiting for AJAX Text

AJAX applications often update text after receiving a server response.

wait.until(

    ExpectedConditions.textToBePresentInElementLocated(

        By.id("status"),

        "Success"

    )

);

 

System.out.println(

    driver.findElement(By.id("status")).getText()

);

This is useful for status messages such as "Loading", "Processing", "Success", "Order Placed", or "Data Loaded".


13. Waiting for AJAX Loading Indicator

Many modern applications display a loading spinner while an asynchronous operation is running.

WebDriverWait wait = new WebDriverWait(

    driver,

    Duration.ofSeconds(15)

);

 

driver.findElement(By.id("search")).sendKeys("Laptop");

 

wait.until(

    ExpectedConditions.invisibilityOfElementLocated(

        By.id("loadingSpinner")

    )

);

 

WebElement result = wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.id("searchResult")

    )

);

 

System.out.println(result.getText());

This approach waits for the application to finish its loading state before interacting with the result.


14. AJAX Search Suggestions

Autocomplete and search suggestion fields are common AJAX scenarios.

WebDriverWait wait = new WebDriverWait(

    driver,

    Duration.ofSeconds(10)

);

 

WebElement search = driver.findElement(

    By.id("search")

);

 

search.sendKeys("Selenium");

 

WebElement suggestion = wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.xpath("//li[contains(text(),'Selenium')]")

    )

);

 

suggestion.click();


15. AJAX Dropdowns

Some dropdowns retrieve their options dynamically after the user selects another field.

driver.findElement(By.id("country"))

      .click();

 

WebDriverWait wait = new WebDriverWait(

    driver,

    Duration.ofSeconds(10)

);

 

WebElement state = wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.id("state")

    )

);

 

state.click();

For example, selecting a country may trigger an AJAX request that loads the corresponding states.


16. AJAX Dependent Dropdown Flow

Select Country

      |

      v

AJAX Request

      |

      v

Server Returns States

      |

      v

State Dropdown Updated

      |

      v

Wait for State Option

      |

      v

Select State


17. Waiting for Dynamic Table Rows

Tables are frequently populated using AJAX calls.

WebDriverWait wait = new WebDriverWait(

    driver,

    Duration.ofSeconds(10)

);

 

driver.findElement(By.id("loadUsers")).click();

 

wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.xpath("//table[@id='users']//tbody/tr")

    )

);

 

List<WebElement> rows = driver.findElements(

    By.xpath("//table[@id='users']//tbody/tr")

);

 

System.out.println("Rows: " + rows.size());


18. AJAX Pagination

Some applications load the next page of records without performing a full browser navigation.

driver.findElement(By.id("nextPage")).click();

 

wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.xpath("//table[@id='users']//tbody/tr")

    )

);

 

System.out.println(

    driver.findElement(By.id("pageNumber")).getText()

);

The important point is to wait for a meaningful change in the page state rather than simply assuming that the next page is ready immediately.


19. AJAX Buttons

An AJAX button may initiate a background request and change its state.

WebElement saveButton = wait.until(

    ExpectedConditions.elementToBeClickable(

        By.id("save")

    )

);

 

saveButton.click();

 

wait.until(

    ExpectedConditions.textToBePresentInElementLocated(

        By.id("message"),

        "Saved"

    )

);


20. AJAX Form Submission

Some forms submit data asynchronously without navigating to another page.

driver.findElement(By.id("name"))

      .sendKeys("John");

 

driver.findElement(By.id("email"))

      .sendKeys("[email protected]");

 

driver.findElement(By.id("submit"))

      .click();

 

wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.id("successMessage")

    )

);

 

Assert.assertEquals(

    driver.findElement(By.id("successMessage")).getText(),

    "Registration Successful"

);


21. AJAX Login

Some login forms authenticate users asynchronously and update the current page rather than performing a complete navigation.

driver.findElement(By.id("username"))

      .sendKeys("admin");

 

driver.findElement(By.id("password"))

      .sendKeys("admin123");

 

driver.findElement(By.id("login"))

      .click();

 

wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.id("dashboard")

    )

);

 

Assert.assertTrue(

    driver.findElement(By.id("dashboard")).isDisplayed()

);


22. AJAX Cart Updates

E-commerce websites often update cart counts asynchronously.

driver.findElement(By.id("addToCart"))

      .click();

 

wait.until(

    ExpectedConditions.textToBePresentInElementLocated(

        By.id("cartCount"),

        "1"

    )

);

 

System.out.println(

    driver.findElement(By.id("cartCount")).getText()

);


23. AJAX Notifications

Applications may display notifications dynamically after an operation.

driver.findElement(By.id("save"))

      .click();

 

WebElement notification = wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.className("notification")

    )

);

 

System.out.println(

    notification.getText()

);


24. AJAX Modal Windows

AJAX requests may dynamically create modal dialogs.

driver.findElement(By.id("openModal"))

      .click();

 

WebElement modal = wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.id("userModal")

    )

);

 

modal.findElement(

    By.id("confirm")

).click();


25. AJAX Tabs

Some tabbed interfaces load content only when a tab is selected.

driver.findElement(By.id("ordersTab"))

      .click();

 

WebElement orders = wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.id("ordersContent")

    )

);

 

System.out.println(

    orders.getText()

);


26. AJAX and StaleElementReferenceException

AJAX updates can replace DOM elements. When an element that Selenium previously located is removed and replaced, the old WebElement reference may become invalid. This can result in a StaleElementReferenceException.

WebElement button = driver.findElement(

    By.id("refresh")

);

 

button.click();

 

button.click();

The second operation can fail if the AJAX update replaced the original element.


27. Handling Stale Elements

A useful approach is to locate the element again after the DOM update.

driver.findElement(By.id("refresh"))

      .click();

 

WebElement button = wait.until(

    ExpectedConditions.elementToBeClickable(

        By.id("refresh")

    )

);

 

button.click();

Another approach is to use a wait that explicitly waits for the old element to become stale and then locates the replacement element.


28. stalenessOf()

The stalenessOf() condition waits until a previously located element is no longer attached to the DOM.

WebElement oldElement = driver.findElement(

    By.id("data")

);

 

driver.findElement(By.id("refresh"))

      .click();

 

wait.until(

    ExpectedConditions.stalenessOf(oldElement)

);

 

WebElement newElement = wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.id("data")

    )

);

This can be useful when an AJAX operation replaces existing content.


29. AJAX and NoSuchElementException

If Selenium searches for an AJAX-generated element before it has been added to the DOM, a NoSuchElementException can occur.

driver.findElement(By.id("load"))

      .click();

 

driver.findElement(By.id("dynamicElement"))

      .click();

The solution is generally to synchronize with the condition that indicates the element is ready.

driver.findElement(By.id("load"))

      .click();

 

WebElement dynamicElement = wait.until(

    ExpectedConditions.elementToBeClickable(

        By.id("dynamicElement")

    )

);

 

dynamicElement.click();


30. AJAX and ElementNotInteractableException

An element can exist in the DOM but still not be ready for interaction. For example, an element may be hidden until an AJAX operation completes.

WebElement element = wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.id("dynamicInput")

    )

);

 

element.sendKeys("Selenium");

Waiting for visibility or clickability is generally more reliable than assuming that DOM presence means the element is ready.


31. AJAX and JavaScript Execution

JavaScript can be used to inspect the current document state or interact with application-specific JavaScript when appropriate. However, JavaScript execution should not replace proper synchronization.

JavascriptExecutor js =

    (JavascriptExecutor) driver;

 

String state = (String) js.executeScript(

    "return document.readyState;"

);

 

System.out.println("State: " + state);

The document.readyState describes document loading, but Selenium's documentation points out that a complete ready state does not guarantee that JavaScript-driven application content has finished loading. :contentReference[oaicite:5]{index=5}


32. document.readyState and AJAX

A common misconception is that document.readyState = complete means every AJAX operation has completed.

document.readyState

Possible values include:

  • loading: The document is still loading.
  • interactive: The document has been parsed and is interactive.
  • complete: The document and its initial resources have completed loading.

However, asynchronous JavaScript can continue changing the page after the initial document reaches its ready state. :contentReference[oaicite:6]{index=6}


33. AJAX vs Page Load

Page LoadAJAX Operation
Usually associated with navigationUsually occurs asynchronously within the current page
Document loading is involvedSpecific content may be updated
WebDriver navigation waits according to page-load strategyAdditional synchronization may be required
May replace the entire documentUsually changes part of the DOM


34. AJAX in Single Page Applications

Single Page Applications, or SPAs, frequently update content dynamically without performing traditional full-page navigation.

Examples of technologies commonly used in modern applications include React, Angular, Vue, and other JavaScript frameworks.

User Action

    |

    v

JavaScript Event

    |

    v

API Request

    |

    v

Response

    |

    v

Application State Updated

    |

    v

DOM Re-rendered

    |

    v

Selenium Interacts with New State

Because the DOM can change after the initial page load, synchronization is particularly important in SPA automation.


35. AJAX and React Applications

React applications can dynamically render and re-render components. Selenium should therefore wait for observable application conditions rather than relying only on page navigation completion.

driver.findElement(By.id("loadProducts"))

      .click();

 

WebElement product = wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.cssSelector(".product-card")

    )

);

 

System.out.println(

    product.getText()

);


36. AJAX and Angular Applications

Angular applications can also perform asynchronous requests and update components dynamically.

driver.findElement(By.id("search"))

      .sendKeys("Laptop");

 

WebElement result = wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.cssSelector(".search-result")

    )

);

 

result.click();


37. AJAX and Vue Applications

Vue-based applications can dynamically update components after user interactions or API responses.

driver.findElement(By.id("loadUsers"))

      .click();

 

wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.cssSelector(".user-row")

    )

);

 

List<WebElement> users = driver.findElements(

    By.cssSelector(".user-row")

);

 

System.out.println(users.size());


38. AJAX and Dynamic Locators

Dynamic applications may generate changing IDs or classes. In such situations, stable attributes and meaningful locator strategies should be preferred.

By result = By.xpath(

    "//div[contains(@class,'result')]"

);

 

WebElement element = wait.until(

    ExpectedConditions.visibilityOfElementLocated(result)

);

Good locator strategies help Selenium find dynamically generated elements reliably.


39. AJAX and CSS Selectors

CSS selectors can be useful for locating dynamic elements.

WebElement result = wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.cssSelector(".search-results .item")

    )

);


40. AJAX and XPath

XPath can be useful when the dynamic element must be located using text or relationships.

WebElement result = wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.xpath("//div[contains(text(),'Selenium')]")

    )

);


41. Waiting for Number of AJAX Results

Sometimes the test needs to wait until multiple elements are loaded.

wait.until(

    ExpectedConditions.numberOfElementsToBeMoreThan(

        By.cssSelector(".product"),

        0

    )

);

 

List<WebElement> products =

    driver.findElements(

        By.cssSelector(".product")

    );

This approach can be useful for dynamically populated product lists or search results.


42. Waiting for AJAX Attribute Changes

AJAX operations may change an element's attributes.

wait.until(driver -> {

    String value = driver.findElement(

        By.id("status")

    ).getAttribute("class");

 

    return value != null &&

           value.contains("completed");

});

Custom conditions can be useful when the application's state is represented by an attribute that does not have a built-in Expected Condition.


43. Custom Explicit Wait Condition

Java Selenium allows a custom condition to be implemented using a lambda expression.

WebDriverWait wait = new WebDriverWait(

    driver,

    Duration.ofSeconds(10)

);

 

wait.until(driver -> {

    String text = driver.findElement(

        By.id("status")

    ).getText();

 

    return text.equals("Completed");

});

Explicit waits can poll the application until the required condition becomes true. :contentReference[oaicite:7]{index=7}


44. Fluent Wait for AJAX Elements

FluentWait allows control over timeout, polling interval, and ignored exceptions.

Wait<WebDriver> wait =

    new FluentWait<WebDriver>(driver)

        .withTimeout(Duration.ofSeconds(15))

        .pollingEvery(Duration.ofMillis(500))

        .ignoring(NoSuchElementException.class);

 

WebElement element = wait.until(

    driver -> driver.findElement(

        By.id("dynamicElement")

    )

);

This can be useful in advanced synchronization scenarios where a custom polling strategy is needed.


45. Implicit Wait with AJAX

An implicit wait tells WebDriver to wait when locating elements for the configured duration.

driver.manage()

      .timeouts()

      .implicitlyWait(

          Duration.ofSeconds(5)

      );

Implicit waits apply globally to element location calls. Selenium documents the default implicit wait as zero. :contentReference[oaicite:8]{index=8}

However, implicit waits are not a replacement for condition-specific synchronization when dealing with AJAX behavior.


46. Do Not Mix Implicit and Explicit Waits Carelessly

Selenium documentation warns against mixing implicit and explicit waits because their interaction can produce unpredictable timing behavior. :contentReference[oaicite:9]{index=9}

For data-driven and AJAX-heavy applications, many frameworks prefer a clear synchronization strategy centered on explicit waits for specific application conditions.


47. AJAX and Loading Spinners

A loading spinner is often an excellent synchronization point because it indicates that an asynchronous operation is in progress.

driver.findElement(By.id("loadData"))

      .click();

 

wait.until(

    ExpectedConditions.invisibilityOfElementLocated(

        By.id("spinner")

    )

);

 

WebElement data = wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.id("data")

    )

);


48. AJAX and Stale DOM

AJAX updates can replace a section of the DOM. Therefore, an element found before the update may no longer represent the current element after the update.

Old DOM

  |

  v

AJAX Update

  |

  v

Old Element Removed

  |

  v

New Element Created

  |

  v

New WebElement Reference Required


49. AJAX and Dynamic Tables

Dynamic tables may initially contain no rows and later receive data from an API.

driver.findElement(By.id("loadData"))

      .click();

 

wait.until(

    ExpectedConditions.presenceOfElementLocated(

        By.cssSelector("#users tbody tr")

    )

);

 

List<WebElement> rows = driver.findElements(

    By.cssSelector("#users tbody tr")

);

 

for (WebElement row : rows) {

    System.out.println(row.getText());

}


50. AJAX and File Upload Status

Some applications upload a file asynchronously and display an upload status after processing.

driver.findElement(By.id("file"))

      .sendKeys(

          "C:\\files\\document.pdf"

      );

 

driver.findElement(By.id("upload"))

      .click();

 

wait.until(

    ExpectedConditions.textToBePresentInElementLocated(

        By.id("uploadStatus"),

        "Upload Complete"

    )

);


51. AJAX and Auto-Save

Modern applications may automatically save changes in the background.

driver.findElement(By.id("title"))

      .sendKeys("Selenium Notes");

 

wait.until(

    ExpectedConditions.textToBePresentInElementLocated(

        By.id("saveStatus"),

        "Saved"

    )

);


52. AJAX and Search Results

A common real-world Selenium scenario is testing an AJAX search component.

driver.findElement(By.id("search"))

      .sendKeys("Selenium");

 

WebElement result = wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.xpath(

            "//div[contains(@class,'result') and contains(.,'Selenium')]"

        )

    )

);

 

result.click();


53. AJAX and Checkbox/Toggle Updates

Some applications send an AJAX request after a checkbox or toggle is changed.

driver.findElement(By.id("notificationToggle"))

      .click();

 

wait.until(

    ExpectedConditions.textToBePresentInElementLocated(

        By.id("status"),

        "Enabled"

    )

);


54. AJAX and Delete Operations

Delete operations may remove an element from the DOM asynchronously.

WebElement row = driver.findElement(

    By.id("userRow")

);

 

driver.findElement(By.id("delete"))

      .click();

 

wait.until(

    ExpectedConditions.stalenessOf(row)

);

Waiting for staleness can confirm that the previous element has been removed from the DOM.


55. AJAX and Refreshing Partial Content

Some applications refresh only a particular section instead of refreshing the whole page.

driver.findElement(By.id("refreshOrders"))

      .click();

 

wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.cssSelector("#orders tbody tr")

    )

);


56. AJAX and JavaScript Alerts

An asynchronous operation may eventually trigger a JavaScript alert. Selenium can wait for the alert before interacting with it.

driver.findElement(By.id("process"))

      .click();

 

WebDriverWait wait = new WebDriverWait(

    driver,

    Duration.ofSeconds(10)

);

 

wait.until(

    ExpectedConditions.alertIsPresent()

);

 

Alert alert = driver.switchTo().alert();

 

System.out.println(alert.getText());

 

alert.accept();


57. AJAX and Frames

If AJAX content is loaded inside an iframe, Selenium must first switch to the correct frame before interacting with elements inside it.

wait.until(

    ExpectedConditions.frameToBeAvailableAndSwitchToIt(

        By.id("paymentFrame")

    )

);

 

WebElement cardNumber = wait.until(

    ExpectedConditions.visibilityOfElementLocated(

        By.id("cardNumber")

    )

);

 

cardNumber.sendKeys("4111111111111111");

 

driver.switchTo().defaultContent();


58. AJAX and Windows/Tabs

Some asynchronous workflows may open a new tab or window after a user action. The automation should wait until the expected window appears before switching.

String originalWindow = driver.getWindowHandle();

 

driver.findElement(By.id("openWindow"))

      .click();

 

wait.until(driver -> driver.getWindowHandles().size() > 1);

 

for (String window : driver.getWindowHandles()) {

    if (!window.equals(originalWindow)) {

        driver.switchTo().window(window);

        break;

    }

}


59. AJAX Synchronization Strategy

A reliable AJAX automation strategy should focus on the state that indicates the application is ready.

ScenarioRecommended Synchronization
Element added dynamicallypresenceOfElementLocated()
Element becomes visiblevisibilityOfElementLocated()
Button becomes clickableelementToBeClickable()
Text changestextToBePresentInElementLocated()
Loading spinner disappearsinvisibilityOfElementLocated()
Old DOM element replacedstalenessOf()
Dynamic custom stateCustom lambda condition
Dynamic frame appearsframeToBeAvailableAndSwitchToIt()


60. Complete AJAX Selenium Example

import java.time.Duration;

 

import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.WebElement;

import org.openqa.selenium.chrome.ChromeDriver;

import org.openqa.selenium.support.ui.ExpectedConditions;

import org.openqa.selenium.support.ui.WebDriverWait;

import org.testng.Assert;

import org.testng.annotations.AfterMethod;

import org.testng.annotations.BeforeMethod;

import org.testng.annotations.Test;

 

public class AjaxTest {

 

    WebDriver driver;

    WebDriverWait wait;

 

    @BeforeMethod

    public void setup() {

        driver = new ChromeDriver();

        driver.manage().window().maximize();

 

        wait = new WebDriverWait(

            driver,

            Duration.ofSeconds(15)

        );

 

        driver.get("https://example.com");

    }

 

    @Test

    public void ajaxSearchTest() {

 

        WebElement search = wait.until(

            ExpectedConditions.visibilityOfElementLocated(

                By.id("search")

            )

        );

 

        search.sendKeys("Selenium");

 

        WebElement result = wait.until(

            ExpectedConditions.visibilityOfElementLocated(

                By.cssSelector(".search-result")

            )

        );

 

        Assert.assertTrue(

            result.isDisplayed()

        );

 

        result.click();

    }

 

    @AfterMethod

    public void tearDown() {

        if (driver != null) {

            driver.quit();

        }

    }

}


61. Complete AJAX Form Example

import java.time.Duration;

 

import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.chrome.ChromeDriver;

import org.openqa.selenium.support.ui.ExpectedConditions;

import org.openqa.selenium.support.ui.WebDriverWait;

import org.testng.Assert;

import org.testng.annotations.AfterMethod;

import org.testng.annotations.BeforeMethod;

import org.testng.annotations.Test;

 

public class AjaxFormTest {

 

    WebDriver driver;

    WebDriverWait wait;

 

    @BeforeMethod

    public void setup() {

        driver = new ChromeDriver();

 

        wait = new WebDriverWait(

            driver,

            Duration.ofSeconds(15)

        );

 

        driver.get("https://example.com/form");

    }

 

    @Test

    public void submitForm() {

 

        driver.findElement(By.id("name"))

              .sendKeys("John");

 

        driver.findElement(By.id("email"))

              .sendKeys("[email protected]");

 

        driver.findElement(By.id("submit"))

              .click();

 

        wait.until(

            ExpectedConditions.visibilityOfElementLocated(

                By.id("successMessage")

            )

        );

 

        String message = driver.findElement(

            By.id("successMessage")

        ).getText();

 

        Assert.assertEquals(

            message,

            "Registration Successful"

        );

    }

 

    @AfterMethod

    public void tearDown() {

        if (driver != null) {

            driver.quit();

        }

    }

}


62. AJAX with Page Object Model

In a Page Object Model framework, synchronization logic can be encapsulated inside page classes so that test classes remain clean.

public class SearchPage {

 

    private WebDriver driver;

    private WebDriverWait wait;

 

    private By searchBox =

        By.id("search");

 

    private By searchResult =

        By.cssSelector(".search-result");

 

    public SearchPage(WebDriver driver) {

        this.driver = driver;

 

        this.wait = new WebDriverWait(

            driver,

            Duration.ofSeconds(10)

        );

    }

 

    public void search(String text) {

 

        WebElement search =

            wait.until(

                ExpectedConditions

                    .visibilityOfElementLocated(searchBox)

            );

 

        search.sendKeys(text);

    }

 

    public void selectResult() {

 

        WebElement result =

            wait.until(

                ExpectedConditions

                    .elementToBeClickable(searchResult)

            );

 

        result.click();

    }

}


63. AJAX POM Test

public class SearchTest {

 

    WebDriver driver;

    SearchPage searchPage;

 

    @BeforeMethod

    public void setup() {

        driver = new ChromeDriver();

 

        driver.get("https://example.com");

 

        searchPage =

            new SearchPage(driver);

    }

 

    @Test

    public void searchTest() {

 

        searchPage.search("Selenium");

 

        searchPage.selectResult();

    }

 

    @AfterMethod

    public void tearDown() {

        if (driver != null) {

            driver.quit();

        }

    }

}


64. AJAX and Data-Driven Testing

AJAX functionality can be combined with TestNG Data Providers to test the same dynamic workflow using multiple data sets.

@DataProvider(name = "searchData")

public Object[][] searchData() {

    return new Object[][] {

        {"Selenium"},

        {"Java"},

        {"TestNG"},

        {"Automation"}

    };

}

 

@Test(dataProvider = "searchData")

public void searchTest(String keyword) {

 

    driver.findElement(By.id("search"))

          .sendKeys(keyword);

 

    WebElement result = wait.until(

        ExpectedConditions.visibilityOfElementLocated(

            By.cssSelector(".search-result")

        )

    );

 

    Assert.assertTrue(

        result.isDisplayed()

    );

}


65. AJAX and Test Reports

AJAX-related failures should be clearly reported because synchronization problems can otherwise be difficult to diagnose.

Useful information to capture includes:

  • Test method name.
  • Input data.
  • Locator involved.
  • Expected condition.
  • Actual application state.
  • Exception message.
  • Screenshot at failure.
  • Current URL.
  • Browser information.
  • Relevant console or application logs where available.


66. Common AJAX Exceptions

ExceptionPossible CauseTypical Solution
NoSuchElementExceptionElement not yet presentWait for presence
ElementNotInteractableExceptionElement exists but is not readyWait for visibility/interactability
ElementClickInterceptedExceptionAnother element or overlay blocks clickWait for overlay/state and clickability
StaleElementReferenceExceptionDOM element was replacedWait for update and locate element again
TimeoutExceptionCondition was not satisfied in timeCheck application state, locator, and timeout


67. Common Mistakes with AJAX Elements

  • Using Thread.sleep() everywhere.
  • Assuming page load completion means AJAX completion.
  • Using an element reference after the DOM has been refreshed.
  • Using unstable dynamic locators.
  • Waiting for the wrong condition.
  • Using very short explicit wait timeouts for slow environments.
  • Using very long timeouts for every operation.
  • Mixing implicit and explicit waits without understanding their interaction.
  • Sharing WebDriver instances between parallel tests.
  • Using JavaScript clicks as a first solution instead of fixing synchronization.
  • Ignoring loading overlays.
  • Failing to identify which AJAX operation caused the failure.


68. Best Practices for AJAX Elements

  • Prefer explicit waits for specific dynamic conditions.
  • Wait for the state that actually indicates readiness.
  • Use stable and meaningful locators.
  • Avoid unnecessary Thread.sleep() calls.
  • Re-locate elements after DOM replacement.
  • Wait for loading indicators to disappear when appropriate.
  • Use Expected Conditions for common synchronization scenarios.
  • Use custom wait conditions for application-specific states.
  • Keep synchronization logic reusable in Page Objects.
  • Use appropriate timeout values based on the application and environment.
  • Keep parallel Selenium execution thread-safe.
  • Capture useful diagnostic information when synchronization fails.


69. AJAX Element Testing Strategy

Identify Dynamic Behavior

        |

        v

Identify Application State

        |

        v

Choose Stable Locator

        |

        v

Choose Expected Condition

        |

        v

Apply Explicit Wait

        |

        v

Locate Current Element

        |

        v

Perform Action

        |

        v

Validate Result

        |

        v

Capture Report


70. Real-World E-Commerce AJAX Example

Consider an e-commerce application where a user searches for a product, selects a suggestion, adds the product to the cart, and waits for the cart count to update.

driver.findElement(By.id("search"))

      .sendKeys("Laptop");

 

WebElement suggestion = wait.until(

    ExpectedConditions.elementToBeClickable(

        By.cssSelector(".suggestion")

    )

);

 

suggestion.click();

 

WebElement addToCart = wait.until(

    ExpectedConditions.elementToBeClickable(

        By.id("addToCart")

    )

);

 

addToCart.click();

 

wait.until(

    ExpectedConditions.textToBePresentInElementLocated(

        By.id("cartCount"),

        "1"

    )

);

 

Assert.assertEquals(

    driver.findElement(By.id("cartCount")).getText(),

    "1"

);


71. Real-World AJAX Workflow

Open E-Commerce Application

          |

          v

Enter Product Search

          |

          v

AJAX Search Request

          |

          v

Wait for Suggestions

          |

          v

Select Product

          |

          v

Wait for Product Details

          |

          v

Click Add to Cart

          |

          v

AJAX Cart Update

          |

          v

Wait for Cart Count

          |

          v

Verify Cart

          |

          v

Test Pass/Fail


72. AJAX Elements and Synchronization Comparison

TechniqueUseSuitability for AJAX
Thread.sleep()Fixed delayLimited
Implicit WaitGlobal element-location waitUseful for basic synchronization
Explicit WaitWait for a specific conditionHighly useful
Expected ConditionsCommon application statesHighly useful
FluentWaitCustom timeout/polling behaviorUseful for advanced cases
Custom LambdaApplication-specific conditionUseful for complex dynamic states


73. AJAX vs Explicit Wait

AJAX itself is not a Selenium waiting mechanism. AJAX is an application-side technique for asynchronous communication and dynamic updates. Selenium's job is to synchronize with the application's resulting state.

AJAX

 |

 |-- Changes application state

 |

 v

Dynamic DOM / UI

 |

 v

Selenium Wait

 |

 v

Required Condition

 |

 v

Selenium Action


74. Practical Exercises

  1. Automate an AJAX search box with dynamic suggestions.
  2. Wait for a dynamically populated table.
  3. Automate a dependent country-state dropdown.
  4. Test an AJAX login form.
  5. Wait for a loading spinner to disappear.
  6. Automate an AJAX add-to-cart operation.
  7. Handle a dynamic modal window.
  8. Handle a stale element after an AJAX refresh.
  9. Wait for dynamically updated status text.
  10. Use a custom Expected Condition for an application-specific state.
  11. Build an AJAX test using Page Object Model.
  12. Combine AJAX automation with a TestNG Data Provider.


75. Interview Questions on AJAX Elements

1. What is AJAX?

AJAX is a technique that allows web applications to exchange data asynchronously and update portions of a page without a complete page reload.

2. Why are AJAX elements difficult to automate?

Because the element or its state may change asynchronously after the initial page has loaded.

3. Which wait is commonly useful for AJAX elements?

Explicit Wait is commonly used because it allows Selenium to wait for a specific application condition.

4. What is the difference between presence and visibility?

Presence means an element exists in the DOM. Visibility means the element is displayed and available for visual interaction.

5. What is an AJAX loading spinner?

It is a visual indicator showing that an asynchronous operation is still processing.

6. How can you wait for a spinner to disappear?

Use an explicit wait with an invisibility condition.

7. What causes StaleElementReferenceException in AJAX applications?

An AJAX update may replace or remove the DOM element represented by the old WebElement reference.

8. How can stale elements be handled?

Wait for the DOM update when appropriate and locate the current element again.

9. Can document.readyState guarantee that AJAX content is ready?

No. JavaScript-driven asynchronous updates can continue after the initial document reaches its ready state. :contentReference[oaicite:10]{index=10}

10. Should Thread.sleep() be used for every AJAX operation?

No. Condition-based explicit waits are generally more reliable and efficient.

11. What is ExpectedConditions?

ExpectedConditions provides reusable conditions for explicit waits, such as visibility, presence, clickability, text, title, and staleness.

12. What is FluentWait?

FluentWait allows customization of timeout, polling interval, and ignored exceptions.

13. Can AJAX elements cause NoSuchElementException?

Yes. If Selenium searches before the dynamically created element is available, the element may not be found.

14. Can AJAX cause ElementNotInteractableException?

Yes. An element may exist but not yet be visible or ready for interaction.

15. How do you automate AJAX search suggestions?

Enter the search text, wait for the suggestion element to become visible or clickable, and then interact with the current suggestion.

16. How do you handle an AJAX-updated table?

Wait for the required table row or data condition and then locate the current rows.

17. How do you handle AJAX-dependent dropdowns?

Select the parent value, wait for the dependent options to load, and then select the required option.

18. Can AJAX testing be combined with POM?

Yes. Page Objects can encapsulate AJAX synchronization and application interaction logic.

19. Can AJAX testing be combined with Data Providers?

Yes. TestNG Data Providers can supply multiple input combinations to AJAX-based test methods.

20. What is the most important principle when automating AJAX applications?

Synchronize with the application's actual state instead of relying on arbitrary fixed delays.


76. Quick Reference Table

ConceptDescription
AJAXAsynchronous communication and dynamic page updates
Dynamic ElementElement that can appear or change after initial page load
Explicit WaitWaits for a specific condition
presenceOfElementLocated()Waits for DOM presence
visibilityOfElementLocated()Waits for visibility
elementToBeClickable()Waits until an element is clickable
textToBePresentInElementLocated()Waits for specific text
invisibilityOfElementLocated()Waits for an element to become invisible
stalenessOf()Waits for an old element to detach from DOM
FluentWaitCustom timeout and polling behavior
Thread.sleep()Fixed delay; generally less reliable for dynamic synchronization
Page Object ModelCan encapsulate AJAX synchronization logic


77. Learning Roadmap for AJAX Elements

  1. Understand HTML DOM and JavaScript basics.
  2. Understand AJAX and asynchronous communication.
  3. Learn Selenium element locators.
  4. Understand static and dynamic elements.
  5. Learn implicit waits.
  6. Learn explicit waits.
  7. Learn Expected Conditions.
  8. Practice visibility and clickability conditions.
  9. Learn to handle loading spinners.
  10. Handle AJAX search suggestions.
  11. Handle dynamic dropdowns and tables.
  12. Understand StaleElementReferenceException.
  13. Learn FluentWait and custom conditions.
  14. Integrate AJAX synchronization with Page Object Model.
  15. Combine AJAX tests with TestNG Data Providers.
  16. Build a reusable Selenium framework for modern dynamic applications.


78. Summary

AJAX elements are common in modern web applications because JavaScript can dynamically load, modify, replace, or display content without performing a complete page refresh.

For Selenium automation, the main challenge is synchronization. The test may execute before the application has finished its asynchronous operation. Selenium's documentation identifies these timing differences as a common source of flaky tests and recommends synchronization mechanisms such as explicit waits. :contentReference[oaicite:11]{index=11}

Explicit waits and Expected Conditions allow Selenium to wait for meaningful states such as element presence, visibility, clickability, expected text, disappearance of a loading indicator, or replacement of an old DOM element. :contentReference[oaicite:12]{index=12}

Reliable AJAX automation should avoid unnecessary fixed delays, use stable locators, re-locate elements after DOM updates, handle stale references appropriately, and keep synchronization logic organized within reusable Page Objects.


79. Course Resources

Learn more about Selenium automation and related testing concepts:

Final Takeaway: AJAX automation is primarily a synchronization challenge. Instead of guessing how long an asynchronous operation will take, Selenium tests should wait for the specific application state required before performing the next action. This makes tests more stable, readable, maintainable, and suitable for modern dynamic web applications.

whatsapp